home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-27 | 11.3 KB | 496 lines | [TEXT/MPS ] |
- //---------------------------------------------------------------------
- //
- // Copyright © 1992 David Peterson.
- // All rights reserved.
- //
- // Permission to use, copy, modify, and distribute this software for
- // any purpose and without fee is hereby granted, provided that the
- // above copyright notice appear in all copies and that both that
- // copyright notice and this permission notice appear in supporting
- // documentation.
- //
- //---------------------------------------------------------------------
-
- #include "InetD.h"
- #include "TCP.h"
- #include "UDP.h"
-
- #include <UFailure.h>
- #include <myUtils.h>
-
- #include <Folders.h>
- #include <Devices.h>
- #include <Resources.h>
- #include <Errors.h>
- #include <Packages.h>
- #include <Sysequ.h>
- #include <GestaltEqu.h>
- #include <ToolUtils.h>
-
- #include <String.h>
- #include <StdArg.h>
- #include <StdIO.h>
-
- void main();
-
- /* Any failure in the program will bring execution back here, if that happens,
- I need to set up another failure handler and try to clean up nicely (which
- attempts to gracefully release all connections) which can fail as well. If
- that happens, just punt.
- */
- void
- main()
- {
- InetD* aDaemon = nil;
- FailInfo fi;
-
- VOLATILE(aDaemon);
-
- InitUDaemonApp(*((long*) DefltStack));
-
- if (CheckSystem()) {
- if (fi.Try()) {
- aDaemon = new InetD;
- FailNIL(aDaemon);
-
- aDaemon->Initialize();
- aDaemon->Run();
-
- delete aDaemon;
-
- fi.Success();
- }
- else if (aDaemon) {
- FailInfo tmp;
-
- if (tmp.Try()) {
- aDaemon->LogIt(true, "InetD:\n\nFailed with OSErr = %d, cleaning up\n", fi.error);
- tmp.Success();
- }
- if (tmp.Try()) {
- delete aDaemon;
- tmp.Success();
- }
- }
- }
- }
-
- /* Check for: AppleEvents, FindFolder, Notification Mgr, Process Mgr, MacTCP.
- Just for grins, I check for A/UX and punt if its around -- you'd have to
- be nuts to try and use a hack like this if you're running UNIX.
-
- The macro is pretty hideous, but simplifies things a bit - I stole it from
- MacApp 3.0.1.
- */
- Boolean
- CheckSystem()
- {
- long response;
- Boolean cont;
-
- #define mHasIt(attr, bit) ((Gestalt(attr, &response) == noErr) && (((response >> bit) & 1) != 0))
-
- cont = (Gestalt(gestaltAUXVersion, &response) != noErr);
-
- cont = (cont && (Gestalt('mtcp', &response) == noErr));
-
- cont = (cont && mHasIt(gestaltAppleEventsAttr, gestaltAppleEventsPresent));
- cont = (cont && mHasIt(gestaltFindFolderAttr, gestaltFindFolderPresent));
- cont = (cont && mHasIt(gestaltNotificationMgrAttr, gestaltNotificationPresent));
- cont = (cont && mHasIt(gestaltOSAttr, gestaltLaunchControl));
- cont = (cont && mHasIt(gestaltOSAttr, gestaltLaunchFullFileSpec));
-
- return cont;
- }
-
- InetD::InetD()
- {
- fLogFile = 0;
- fTCP = nil;
- fUDP = nil;
-
- FailOSErr(OpenDriver("\p.ipp", &fDriverRef));
- }
-
- InetD::~InetD()
- {
- if (fTCP) delete fTCP;
- if (fUDP) delete fUDP;
-
- this->LogIt(false, "Shutting down\n");
-
- if (fLogFile) FSClose(fLogFile);
- }
-
- void
- InetD::Initialize()
- {
- Inherited::Initialize();
-
- short resFile;
- short curResFile;
-
- short vRefNum;
- long dirID;
-
- FSSpec logfile;
- Str255 prepname;
- Str255 logname;
-
- GetIndString(prepname, kFileNames, kPrepFile);
- GetIndString(logname, kFileNames, kLogFile);
-
- FindFolder(kOnSystemDisk, kPreferencesFolderType, false, &vRefNum, &dirID);
-
- if (FSMakeFSSpec(vRefNum, dirID, logname, &logfile) == fnfErr)
- FSpCreate(&logfile, 'MPS ', 'TEXT', smSystemScript);
-
- FailOSErr(FSpOpenDF(&logfile, fsRdWrPerm, &fLogFile));
- FailOSErr(SetFPos(fLogFile, fsFromLEOF, 0));
-
- this->LogIt(false, "Starting up\n");
-
- if (FSMakeFSSpec(vRefNum, dirID, prepname, &fPrepFile) == fnfErr)
- FSpCreateResFile(&fPrepFile, 'inet', 'prep', smSystemScript);
-
- resFile = FSpOpenResFile(&fPrepFile, fsRdPerm);
- FailResError();
- curResFile = SwitchResFile(resFile);
-
- this->NewTCPListener();
- this->NewUDPListener();
-
- SwitchResFile(curResFile);
- CloseResFile(resFile);
- }
-
- /* Encapsulate the process some so that it can be easily done from
- AEResetHandler. The Initialize will return false if there were
- no 'TCP ' resources found, this isn't neccessarily an error
- because its possible that none were created with the control panel.
- */
- void
- InetD::NewTCPListener()
- {
- TCPListener* nu;
-
- if (fTCP) {
- delete fTCP;
- fTCP = nil;
- }
-
- nu = new TCPListener(this);
- FailNIL(nu);
-
- if (nu->Initialize())
- fTCP = nu;
- else
- delete nu;
- }
-
- void
- InetD::NewUDPListener()
- {
- UDPListener* nu;
-
- if (fUDP) {
- delete fUDP;
- fUDP = nil;
- }
-
- nu = new UDPListener(this);
- FailNIL(nu);
-
- if (nu->Initialize())
- fUDP = nu;
- else
- delete nu;
- }
-
- void
- InetD::InstallAEHandlers()
- {
- Inherited::InstallAEHandlers();
-
- FailOSErr(AEInstallEventHandler(kCoreEventClass, kAEApplicationDied,
- (EventHandlerProcPtr) &AEDeathHandler, (long) this, false));
-
- FailOSErr(AEInstallEventHandler('INET', 'TNFY',
- (EventHandlerProcPtr) &AETCPNotificationHandler, (long) this, false));
-
- FailOSErr(AEInstallEventHandler('INET', 'UNFY',
- (EventHandlerProcPtr) &AEUDPNotificationHandler, (long) this, false));
-
- FailOSErr(AEInstallEventHandler('INET', 'RSET',
- (EventHandlerProcPtr) &AEResetHandler, (long) this, false));
- }
-
- void
- InetD::Launch(StreamPtr stream, FSSpec* process, AEEventID type, PSN* psn)
- {
- OSErr result;
- AppleEvent theEvent;
- AEAddressDesc myAddress;
- AEDesc launchDesc;
- LaunchParamBlockRec lpb;
- Boolean theyare;
-
- theyare = this->IsRunning(process->name, psn);
-
- FailOSErr(AECreateDesc(typeProcessSerialNumber, (Ptr) psn, sizeof(PSN), &myAddress));
- FailOSErr(AECreateAppleEvent('INET', type, &myAddress, kAutoGenerateReturnID, kAnyTransactionID, &theEvent));
- FailOSErr(AEPutParamPtr(&theEvent, 'STRM', typeLongInteger, (Ptr) &stream, sizeof(StreamPtr)));
-
- if (theyare) {
- result = AESend(&theEvent, nil, kAENoReply, kAEHighPriority, 0, nil, nil);
- }
- else {
- FailOSErr(AECoerceDesc(&theEvent, typeAppParameters, &launchDesc));
-
- HLock(launchDesc.dataHandle);
-
- lpb.launchAppParameters = (AppParameters*) *(launchDesc.dataHandle);
- lpb.launchBlockID = extendedBlock;
- lpb.launchEPBLength = extendedBlockLen;
- lpb.launchFileFlags = 0;
- lpb.launchControlFlags = launchContinue + launchNoFileFlags;
- lpb.launchAppSpec = process;
-
- result = LaunchApplication(&lpb);
-
- HUnlock(launchDesc.dataHandle);
-
- psn->highLongOfPSN = lpb.launchProcessSN.highLongOfPSN;
- psn->lowLongOfPSN = lpb.launchProcessSN.lowLongOfPSN;
-
- AEDisposeDesc(&launchDesc);
- }
-
- AEDisposeDesc(&theEvent);
- AEDisposeDesc(&myAddress);
-
- FailOSErr(result);
- }
-
- Boolean
- InetD::IsRunning(Str63 name, PSN* ts)
- {
- ProcessSerialNumber psn;
- ProcessInfoRec prc;
- Boolean found = false;
- Str63 pname;
-
- psn.highLongOfPSN = 0;
- psn.lowLongOfPSN = kNoProcess;
-
- prc.processInfoLength = sizeof(ProcessInfoRec);
- prc.processName = pname;
- prc.processAppSpec = nil;
-
- while (!found && (GetNextProcess(&psn) == noErr)) {
- if (GetProcessInformation(&psn, &prc) == noErr) {
- if (IUCompString(pname, name) == 0) {
- ts->highLongOfPSN = psn.highLongOfPSN;
- ts->lowLongOfPSN = psn.lowLongOfPSN;
- found = true;
- }
- }
- }
-
- return found;
- }
-
- void
- InetD::DoNull()
- {
- short resFile;
- short curResFile;
-
- resFile = FSpOpenResFile(&fPrepFile, fsRdPerm);
- FailResError();
- curResFile = SwitchResFile(resFile);
-
- if (fTCP) fTCP->DoNull();
- if (fUDP) fUDP->DoNull();
-
- SwitchResFile(curResFile);
- CloseResFile(resFile);
- }
-
- void
- InetD::LogIt(Boolean postit, char* form, ...)
- {
- va_list ap;
- long len;
- unsigned long time;
- Str63 datestr;
- Str63 timestr;
- char datetime[255];
- char str[255];
-
- FailInfo fi;
-
- str[0] = 0;
- datetime[0] = 0;
-
- va_start(ap, form);
- vsprintf(str, form, ap);
- va_end(ap);
-
- if (postit && fi.Try()) {
- this->PostNotification(str);
- fi.Success();
- }
-
- GetDateTime(&time);
- IUDateString(time, shortDate, datestr);
- IUTimeString(time, true, timestr);
-
- sprintf(datetime, "%P\t%P:\t\t", datestr, timestr);
-
- if (fi.Try()) {
- len = strlen(datetime);
- if (fLogFile) FailOSErr(FSWrite(fLogFile, &len, datetime));
-
- len = strlen(str);
- if (fLogFile) FailOSErr(FSWrite(fLogFile, &len, str));
- fi.Success();
- }
- }
-
- pascal OSErr
- AEDeathHandler(AppleEvent* messagein, AppleEvent* /*reply*/, long refIn)
- {
- AEDesc psnDesc;
- OSErr theErr = noErr;
- InetD* inet = (InetD*) refIn;
- PSN psn;
-
- if ((theErr = AEGetParamDesc(messagein, keyProcessSerialNumber, typeProcessSerialNumber, &psnDesc)) == noErr) {
- psn.highLongOfPSN = ((PSN*) *psnDesc.dataHandle)->highLongOfPSN;
- psn.lowLongOfPSN = ((PSN*) *psnDesc.dataHandle)->lowLongOfPSN;
-
- AEDisposeDesc(&psnDesc);
- }
-
- short save = TurnOffInterrupts();
-
- inet->fTCP->UnNotify(&psn);
- inet->fUDP->UnNotify(&psn);
-
- TurnOnInterrupts(save);
-
- inet->fUDP->ListenAgain(&psn);
-
- return theErr;
- }
-
- pascal OSErr
- AETCPNotificationHandler(AppleEvent* messagein, AppleEvent* /*reply*/, long refIn)
- {
- ProcPtr proc = nil;
- StreamPtr stream = nil;
- Ptr usrPtr = nil;
- PSN psn;
- InetD* inet = (InetD*) refIn;
-
- AEDesc streamDesc, notifyDesc, psnDesc, ptrDesc;
-
- FailInfo fi;
-
- if (fi.Try()) {
- FailOSErr(AEGetParamDesc(messagein, 'STRM', typeLongInteger, &streamDesc));
- FailOSErr(AEGetParamDesc(messagein, 'ASR ', typeLongInteger, ¬ifyDesc));
- FailOSErr(AEGetParamDesc(messagein, 'USRP', typeLongInteger, &ptrDesc));
- FailOSErr(AEGetParamDesc(messagein, keyProcessSerialNumber, typeProcessSerialNumber, &psnDesc));
-
- stream = *((StreamPtr*) *streamDesc.dataHandle);
- proc = *((ProcPtr*) *notifyDesc.dataHandle);
- usrPtr = *((Ptr*) *ptrDesc.dataHandle);
- psn.highLongOfPSN = ((PSN*) *psnDesc.dataHandle)->highLongOfPSN;
- psn.lowLongOfPSN = ((PSN*) *psnDesc.dataHandle)->lowLongOfPSN;
-
- AEDisposeDesc(&streamDesc);
- AEDisposeDesc(¬ifyDesc);
- AEDisposeDesc(&psnDesc);
- AEDisposeDesc(&psnDesc);
-
- fi.Success();
- }
- else {
- inet->LogIt(false, "Malformed TCP notification AE\n");
- }
-
- short save = TurnOffInterrupts();
- inet->fTCP->NotifyMe(&psn, stream, proc, usrPtr);
- TurnOnInterrupts(save);
-
- return fi.error;
- }
-
- pascal OSErr
- AEUDPNotificationHandler(AppleEvent* messagein, AppleEvent* /*reply*/, long refIn)
- {
- ProcPtr proc = nil;
- StreamPtr stream = nil;
- Ptr usrPtr = nil;
- PSN psn;
- InetD* inet = (InetD*) refIn;
-
- AEDesc streamDesc, notifyDesc, psnDesc, ptrDesc;
-
- FailInfo fi;
-
- if (fi.Try()) {
- FailOSErr(AEGetParamDesc(messagein, 'STRM', typeLongInteger, &streamDesc));
- FailOSErr(AEGetParamDesc(messagein, 'ASR ', typeLongInteger, ¬ifyDesc));
- FailOSErr(AEGetParamDesc(messagein, 'USRP', typeLongInteger, &ptrDesc));
- FailOSErr(AEGetParamDesc(messagein, keyProcessSerialNumber, typeProcessSerialNumber, &psnDesc));
-
- stream = *((StreamPtr*) *streamDesc.dataHandle);
- proc = *((ProcPtr*) *notifyDesc.dataHandle);
- usrPtr = *((Ptr*) *ptrDesc.dataHandle);
- psn.highLongOfPSN = ((PSN*) *psnDesc.dataHandle)->highLongOfPSN;
- psn.lowLongOfPSN = ((PSN*) *psnDesc.dataHandle)->lowLongOfPSN;
-
- AEDisposeDesc(&streamDesc);
- AEDisposeDesc(¬ifyDesc);
- AEDisposeDesc(&psnDesc);
- AEDisposeDesc(&psnDesc);
-
- fi.Success();
- }
- else {
- inet->LogIt(false, "Malformed UDP notification AE\n");
- }
-
- short save = TurnOffInterrupts();
- inet->fUDP->NotifyMe(&psn, stream, proc, usrPtr);
- TurnOnInterrupts(save);
-
- return fi.error;
- }
-
- pascal OSErr
- AEResetHandler(AppleEvent* /*messagein*/, AppleEvent* /*reply*/, long refIn)
- {
- short resFile;
- short curResFile;
- InetD* inet = (InetD*) refIn;
-
- inet->LogIt(false, "Caught reset signal\n");
-
- resFile = FSpOpenResFile(&inet->fPrepFile, fsRdPerm);
- FailResError();
- curResFile = SwitchResFile(resFile);
-
- inet->NewTCPListener();
- inet->NewUDPListener();
-
- SwitchResFile(curResFile);
- CloseResFile(resFile);
-
- return noErr;
- }
-
-